#include <bits/stdc++.h>
#define pb push_back
#define vec vector<int>

using namespace std;

const int MAXN = 2e5+10;

int h[MAXN],cnt = 1,n,m,dx[MAXN],dy[MAXN],fa[MAXN],dep[MAXN],go[MAXN<<1];
bool vis[MAXN];

struct edge{int v,nxt;}e[MAXN<<1];

void link(int x,int y){e[++cnt] = (edge){y,h[x]};h[x] = cnt;}

vec getroad(int x,int y){vec path;while(x != y) path.pb(y),y = fa[y];path.pb(x);reverse(path.begin(),path.end());return path;}

void print(vec path){printf("%d",path.size());for(int i = 0;i < path.size();i++) printf(" %d",path[i]);puts("");}

int lca(int x,int y){
	if(dep[x] < dep[y]) swap(x,y);
	while(dep[x] != dep[y]) x = fa[x];
	while(x != y) x = fa[x],y = fa[y];
	return x;
}

void upd(int x,int y){
	for(int i = x;i != y;i = fa[i]) {
		if(!dx[i] && !dy[i]) dx[i] = x,dy[i] = y;
		else{
			puts("YES");
			if(dep[dy[i]] < dep[y]) swap(y,dy[i]),swap(x,dx[i]);
			int a = dy[i] , b = lca(dx[i],x);
			print(getroad(a,b));
			vec p1 = getroad(y,a),p2 = getroad(b,x);
			reverse(p1.begin(),p1.end()); reverse(p2.begin(),p2.end());
			for(int j = 0;j < p2.size();j++) p1.pb(p2[j]);
			
			print(p1);
			p1 = getroad(b,dx[i]);
			reverse(p1.begin(),p1.end());
			p1.insert(p1.begin(),a);
			print(p1);
			exit(0);
		}
	}
}

			
void dfs(int x,int p){
	fa[x] = p;vis[x] = 1;dep[x] = dep[p]+1;
	for(int i = h[x];i;i = e[i].nxt){int y = e[i].v;if(y == p) continue;if(!vis[y]) dfs(y,x);else if(!go[i]) upd(x,y),go[i^1] = go[i] = 1;}
}

int main (){
	scanf("%d %d",&n,&m);
	for(int i = 1;i <= m;i++){
		int x,y;scanf("%d %d",&x,&y);
		link(x,y);link(y,x);
	}
	for(int i = 1;i <= n;i++) if(!vis[i]) dfs(i,0);
	puts("NO");
	return 0;
}
